package lion.framework.core;

import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import lion.dev.lang.Init;
import lion.framework.core.anno.AnnoProcessor;
import lion.framework.core.anno.AnnotationProcessorManager;
import lion.framework.core.anno.IAnnotationProcessor;
import lion.framework.core.conf.Config;
import lion.framework.core.conf.ConfigManager;
import lion.framework.core.conf.IConfigLoader;
import lion.framework.core.conf.loader.XMLConfigLoader;
import lion.framework.core.util.ClassScanner;
import lion.framework.core.util.InitializerComparator;

/**
 * 应用初始化类,扫描注解，并初始化各个Initializer <br/>
 * framework default order between
 *
 * <pre>
 * time   2013 2013-4-24 上午11:33:09
 * mail   hl_0074@sina.com
 * </pre>
 *
 * @author lion
 */
public class ApplicationInitializer {

	private static final List<Init> initializers = Collections.synchronizedList(new ArrayList<Init>());
	private static Log log = LogFactory.getLog(ApplicationInitializer.class);

	public static void init() throws Exception {

		// regist system config loader first
		initFrameworkConfig();
		// init annotation
		initAnnotations();

		// if the system is not installed,no initializer should execute
		// if (!SystemInstaller.isInstalled()) {
		// log.debug("system not installed,the initialization will not
		// perform");
		// return;
		// }
		Collections.sort(initializers, new InitializerComparator());
		for (Init init : initializers) {
			if (log.isDebugEnabled()) {
				log.debug(String.format("init %s", init.getClass().getName()));
			}
			try {
				long s = System.currentTimeMillis();
				init.init();
				log.info("init " + init.getClass().getName() + ":" + (System.currentTimeMillis() - s) + " ms");
			} catch (Exception e) {
				if (log.isErrorEnabled()) {
					log.error("init error", e);
				}
			}
		}
	}

	private static void initFrameworkConfig() throws Exception {

		IConfigLoader loader = new XMLConfigLoader("framework.xml");
		Config config = new Config(loader);
		config.load();
		ConfigManager.addConfig("framework", config);
	}

	private static void initAnnotations() throws Exception {

		List<Class<?>> classes = new ArrayList<>();
		URLClassLoader loader = (URLClassLoader) ApplicationInitializer.class.getClassLoader();
		URL[] urls = loader.getURLs();
		for (URL url : urls) {
			URI uri = url.toURI();
			if (uri.getScheme().equals("file")) {
				File file = new File(uri);
				classes.addAll(ClassScanner.scan(file));
			}
		}

		// 先 注册annotation处理类
		for (Class<?> clazz : classes) {
			AnnoProcessor anno = clazz.getAnnotation(AnnoProcessor.class);
			if (anno == null || !(IAnnotationProcessor.class.isAssignableFrom(clazz))) {
				continue;
			}
			if (log.isInfoEnabled()) {
				log.info("AnnotationProcessor found:" + clazz.getName());
			}
			try {
				AnnotationProcessorManager.regist(anno.value(), (IAnnotationProcessor) clazz.newInstance());
			} catch (Exception e) {
				if (log.isErrorEnabled()) {
					log.error("regist annotation processor error", e);
				}
				throw e;
			}
		}
		// 扫描
		AnnotationProcessorManager.processAnnotations(classes);
	}

	public static void registInitializer(Init init) {

		initializers.add(init);
	}
}
